package com.lxk.mall.pms.mapper;

import cn.hutool.core.lang.Assert;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.lxk.mall.pms.domain.PmsProductSku;
import com.lxk.mall.pms.domain.vo.spu.PmsProductSkuVo;
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;

import java.util.List;

/**
 * 商品skuMapper接口
 *
 * @author Lion Li
 * @date 2024-06-06
 */
public interface PmsProductSkuMapper extends BaseMapperPlus<PmsProductSku, PmsProductSkuVo> {

    default List<PmsProductSku> selectListBySpuId(Long spuId) {
        return selectList(new LambdaQueryWrapper<PmsProductSku>().eq(PmsProductSku::getSpuId, spuId));
    }

    /**
     * 更新 SKU 库存（增加）
     *
     * @param id        编号
     * @param incrCount 增加库存（正数）
     */
    default void updateStockIncr(Long id, Integer incrCount) {
        Assert.isTrue(incrCount > 0);
        LambdaUpdateWrapper<PmsProductSku> lambdaUpdateWrapper = new LambdaUpdateWrapper<PmsProductSku>()
            .setSql(" stock = stock + " + incrCount)
            .eq(PmsProductSku::getId, id);
        update(null, lambdaUpdateWrapper);
    }

    /**
     * 更新 SKU 库存（增加）
     *
     * @param id        编号
     * @param incrCount 增加库存（正数）
     */
    default void addStockIncr(Long id, Integer incrCount) {
        Assert.isTrue(incrCount > 0);
        LambdaUpdateWrapper<PmsProductSku> lambdaUpdateWrapper = new LambdaUpdateWrapper<PmsProductSku>()
            .setSql(" stock = stock + " + incrCount)
            .eq(PmsProductSku::getId, id);
        update(null, lambdaUpdateWrapper);
    }

    /**
     * SKUID回滚预扣库存接口
     *
     * @param id        编号
     * @param incrCount 增加库存（正数）
     */
    default int addStockForeIncr(Long id, Integer incrCount) {
        Assert.isTrue(incrCount > 0);
        LambdaUpdateWrapper<PmsProductSku> lambdaUpdateWrapper = new LambdaUpdateWrapper<PmsProductSku>()
            .setSql(" stock = stock + " + incrCount)
            .setSql(" stock_fore = stock_fore - " + incrCount)
            .eq(PmsProductSku::getId, id)
            .ge(PmsProductSku::getStockFore, incrCount);
        return update(null, lambdaUpdateWrapper);
    }

    /**
     * 更新 SKU 库存（减少）
     *
     * @param id        编号
     * @param incrCount 减少库存（负数）
     * @return 更新条数
     */
    default int updateStockDecr(Long id, Integer incrCount) {
        Assert.isTrue(incrCount < 0);
        LambdaUpdateWrapper<PmsProductSku> updateWrapper = new LambdaUpdateWrapper<PmsProductSku>()
            .setSql(" stock = stock + " + incrCount) // 负数，所以使用 + 号
            .eq(PmsProductSku::getId, id)
            .ge(PmsProductSku::getStock, -incrCount); // cas 逻辑
        return update(null, updateWrapper);
    }

    /**
     * 更新 SKU 库存（减少）
     *
     * @param id        编号
     * @param incrCount 减少库存（负数）
     * @return 更新条数
     */
    default int cutStockDecr(Long id, Integer incrCount) {
        Assert.isTrue(incrCount > 0);
        LambdaUpdateWrapper<PmsProductSku> updateWrapper = new LambdaUpdateWrapper<PmsProductSku>()
            .setSql(" stock = stock - " + incrCount)
            .eq(PmsProductSku::getId, id)
            .ge(PmsProductSku::getStock, incrCount); // cas 逻辑
        return update(null, updateWrapper);
    }

    /**
     * SKUID预扣库存接口
     *
     * @param id        编号
     * @param incrCount 减少库存（负数）
     * @return 更新条数
     */
    default int cutStockForeDecr(Long id, Integer incrCount) {
        Assert.isTrue(incrCount > 0);
        LambdaUpdateWrapper<PmsProductSku> updateWrapper = new LambdaUpdateWrapper<PmsProductSku>()
            .setSql(" stock = stock - " + incrCount)
            .setSql(" stock_fore = stock_fore + " + incrCount)
            .eq(PmsProductSku::getId, id)
            .ge(PmsProductSku::getStock, incrCount); // cas 逻辑
        return update(null, updateWrapper);
    }

    /**
     * 减少stock_fore
     *
     * @param id
     * @param incrCount
     * @return
     */
    default int actCutStockFore(Long id, Integer incrCount) {
        Assert.isTrue(incrCount > 0);
        LambdaUpdateWrapper<PmsProductSku> updateWrapper = new LambdaUpdateWrapper<PmsProductSku>()
            .setSql(" stock_fore = stock_fore - " + incrCount)
            .eq(PmsProductSku::getId, id)
            .ge(PmsProductSku::getStockFore, incrCount); // cas 逻辑
        return update(null, updateWrapper);
    }

    int lockStockBySkuId(Long id, Integer count);
}
